/**
 * WTF Engine
 *
 * Released under the terms of the Worcester Public License,
 * see LICENSE in the root folder. This program comes with
 * no warranty whatsoever, implied or otherwise. All rights
 * other than those explicitly specified in the LICENSE document
 * are reserved.
 **
 * Generic Multithreading Support
 *
 * Provides the following
 *	- Abstracts the thread support of the native OS
 *	- Work pools of threads
 *	- Futures, which are evaluated by threads in the work pool
 **
 * Author: Sean Micklethwaite
 **/

#ifndef __threadH__
#define __threadH__

#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include "work.h"
#include "functor.h"


namespace WtfEngine
{
	class Thread : public boost::thread
	{

	};



	/**
	 *  Future is a computation, whose result will be needed in future.
	 * 	It is an ADT for representing a computation
	 *	which needs to be performed, of which the result
	 *	will be used sometime in the future.
	 **/
	class Future : public WorkItem
	{
	private:
		Functor::tRef	mFunctor;

	public:
		Future() : WorkItem() {};

		/**
		 * Constructor/Create:
		 * Initialises the work item.
		 *
		 * Specification:
		 * PRE:	�(F memberof WorkList)
		 * POS: �Evaluated && WorkList = WorkList0 U {F}
		 **/
		Future(Functor::tRef& f)
			: WorkItem(){
			Create(f);
		}

		Future(Functor* f)
			: WorkItem(){
			Create(f);
		}

		virtual ~Future();

		void Create(Functor::tRef& f){
			mFunctor = f;
			this->WorkItem::Create();
		}

		void Create(Functor* f){
			mFunctor = f;
			this->WorkItem::Create();
		}

		/**
		 * GetResult:
		 * Tries to get the result of the functor which is bound to this
		 * future. If the result has not yet been evaluated, it will be
		 * calculated and then returned.
		 *
		 * Specification:
		 * PRE:	�Evaluated => F memberof WorkList
		 * POS: �Evaluated0 => Evaluated && WorkList = WorkList0 \ {F}
		 **/
		template <class T>
		const T & GetResult()
		{
			Sync();
			return static_cast<ValueFunctor<T>*>(&*mFunctor)->GetValue();
		};

	protected:
		void operator()(){
			(*mFunctor)();
		};
	};

	template <class tRet, class tArg>
	class BoundFuture : public WorkItem
	{
	private:
		BoundFunctor<tRet,tArg>	mFunctor;

	public:
		typedef typename BoundFunctor<tRet,tArg>::tFunc tFunc;

		BoundFuture() : WorkItem(), mFunctor()
			{};
		BoundFuture(const tFunc& f, const tArg& a)
			: WorkItem(), mFunctor(f, a){
			this->WorkItem::Create();
		};

		void Create(const typename BoundFunctor<tRet,tArg>::tFunc& f, const tArg& a)
		{
			mFunctor.Create(f, a);
			this->WorkItem::Create();
		};

		const tRet & GetResult()
		{
			Sync();
			return mFunctor.GetValue();
		};

		void operator ()(){
			mFunctor();
		};
	};
}

#endif
